/*
 * Copyright the original author or authors.
 */
package com.derbysoft.core;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * <code>Sort</code> 排序对象
 *
 * @author snowway
 * @since 2008-11-7
 */
public class Sorter implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 220961561706707123L;

    /**
     * 排序类型
     */
    private static enum Type {

        /**
         * 升序
         */
        ASCENDING,

        /**
         * 降序
         */
        DESCENDING
    }

    /**
     * 排序指示对象
     */
    private static class Sort implements Serializable {

        /**
         *
         */
        private static final long serialVersionUID = -6427876894629910120L;

        private String property;

        private Type type;

        public Sort(String property, Type type) {
            this.property = property;
            this.type = type;
        }

        public boolean isAscending() {
            return type == Type.ASCENDING;
        }

        @Override
        public String toString() {
            return property + " " + (type == Type.ASCENDING ? "asc" : "desc");
        }
    }

    private Map<String, Sort> sortMap = new LinkedHashMap<String, Sort>();


    /**
     * 升序
     *
     * @param property sort property
     * @return this
     */
    public Sorter asc(String property) {
        if (sortMap.containsKey(property)) {
            sortMap.remove(property);
        }
        sortMap.put(property, new Sort(property, Type.ASCENDING));
        return this;
    }

    /**
     * 降序
     *
     * @param property sort property
     * @return this
     */
    public Sorter desc(String property) {
        if (sortMap.containsKey(property)) {
            sortMap.remove(property);
        }
        sortMap.put(property, new Sort(property, Type.DESCENDING));
        return this;
    }

    /**
     * 附加order语句到hql上
     *
     * @param hql hql
     * @return decorated hql
     */
    public String decorate(String hql) {

        if (sortMap.isEmpty()) {
            return hql;
        }

        StringBuilder queryBuilder = new StringBuilder(hql);
        if (StringUtils.containsIgnoreCase(hql, "order by")) {
            queryBuilder.append(",").append(StringUtils.join(sortMap.values(), ","));
        } else {
            queryBuilder.append(" order by ").append(StringUtils.join(sortMap.values(), ","));
        }
        return queryBuilder.toString();
    }


    /**
     * 附加order语句到 {@link Criteria} 上
     *
     * @param criteria {@link Criteria}
     * @return Criteria
     */
    public Criteria decorate(Criteria criteria) {
        if (sortMap.isEmpty()) {
            return criteria;
        }

        for (Map.Entry<String, Sort> entry : sortMap.entrySet()) {
            String property = entry.getKey();
            Sort sort = entry.getValue();
            criteria.addOrder(sort.isAscending() ? Order.asc(property) : Order.desc(property));
        }
        return criteria;
    }
}
